package com.ruoyi.web.controller.dj;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ExecUtil;
import com.ruoyi.common.utils.biz.BizModule;
import com.ruoyi.common.utils.biz.CommonUtil;
import com.ruoyi.common.utils.biz.PathUtil;
import com.ruoyi.common.utils.biz.ResultSaveModule;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.web.vo.DynamicReviseCalVo;
import com.ruoyi.web.vo.DynamicReviseVerticalVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * <p>
 *  多模型计算与预报-动态修正计算
 * </p>
 *
 * @author liuhl
 * @since 2024-05-30
 */
@RestController
@RequestMapping("/dj/dynamic")
@AllArgsConstructor
@Slf4j
@Api(tags = "多模型计算与预报-动态修正计算")
public class DynamicReviseController {

    @Autowired
    private RedisTemplate redisTemplate;


    @PostMapping("/cal")
    @ApiOperation(value = "计算", notes = "根据页面输入条件动态修正计算出结果", httpMethod = "POST")
    public AjaxResult cal(@RequestBody DynamicReviseCalVo vo) {

        String key = MD5.create().digestHex(vo.toString());
        String results = "";
        Object o = redisTemplate.opsForValue().get(key);
        if (o != null) {
            results = (String)o;
        }else {
            String codePath = PathUtil.codeModuleDir(BizModule.MODEL_CAL) + PathUtil.moduleDirs().getModelCal().get("dynamicRev");
            String tmpPath = PathUtil.tmpModuleDir(BizModule.MODEL_CAL);
            String type = vo.getType();
            String command = "";
            if ("orbit".equals(type)) {
                command = "python "
                        + codePath
                        + " " + type
                        + " " + vo.getSateName()
                        + " " + vo.getStartTime()
                        + " " + vo.getEndTime()
                        + " " + vo.getSpan()
                        + " " + tmpPath
                        + " " + vo.getTypes()
                        + " " + vo.getFrequence();
            }

            if ("global".equals(type)) {
                command = "python "
                        + codePath
                        + " " + type
                        + " " + vo.getLatSpace()
                        + " " + vo.getLonSpace()
                        + " " + vo.getLevel()
                        + " " + vo.getStartTime()
                        + " " + vo.getEndTime()
                        + " " + vo.getSpan()
                        + " " + vo.getLonWest()
                        + " " + vo.getLonEast()
                        + " " + vo.getLatSouth()
                        + " " + vo.getLatNorth()
                        + " " + vo.getTypes()
                        + " " + vo.getFrequence();
            }

            results = ExecUtil.execCmdWithResult(command);
            if (results == null || !results.contains("###")) {
                return AjaxResult.error(results);
            }
            redisTemplate.opsForValue().set(key,results,1, TimeUnit.HOURS);
        }

        String[] split = results.split("###");
        String log = split[0];
        String dataJsonStr = split[1].trim();

        if (dataJsonStr.startsWith("{")) {
            dataJsonStr = "[" + dataJsonStr + "]";
        }

        Object data = JSONUtil.parseArray(dataJsonStr);

        List<String> jsonStrList = new ArrayList<>();
        if (StrUtil.isNotBlank(split[2])){
            String jsonPathArrayStr = split[2];
            jsonStrList = JSONUtil.parseArray(jsonPathArrayStr).toList(String.class)
                    .stream()
                    .map(path -> {
                        return CommonUtil.readStrData(new File(path), null);
                    })
                    .collect(Collectors.toList());
        }

        Map<String, Object> resultMap = MapUtil.builder(new HashMap<String, Object>())
                .put("log", log)
                .put("data", data)
                .put("tableData", jsonStrList)
                .build();
        return AjaxResult.success(resultMap);

    }

    @ApiOperation(value = "计算结果下载",consumes="application/octet-stream")
    @PostMapping("/download")
    public void download(@RequestBody DynamicReviseCalVo vo, HttpServletResponse response) {

        String key = MD5.create().digestHex(vo.toString());
        Object cache = redisTemplate.opsForValue().get(key);
        if (cache == null) {
            cal(vo);
            cache = redisTemplate.opsForValue().get(key);
        }
        String str = (String) cache;
        String[] split = str.split("###");
        String dataJsonStr = split[1];
        String url = PathUtil.tmpModuleDir(BizModule.MODEL_CAL)+ "/"+ DateUtil.format(new Date(),"yyyyMMddHHmmss")+".zip";
        File res = null;
        String jsonPath = null;
        try {
            if ("global".equals(vo.getType())) {
                //图片
                List<String> pngs = JSONUtil.toList(dataJsonStr, String.class);
                List<File> collect = pngs.stream().map(a -> new File(a)).collect(Collectors.toList());
                //json数据文件
                String jsonPathArrayStr = split[2];
                List<File> jsonPathList = JSONUtil.parseArray(jsonPathArrayStr).toList(String.class)
                        .stream()
                        .map(a -> new File(a)).collect(Collectors.toList());
                collect.addAll(jsonPathList);

                File[] files = ArrayUtil.toArray(collect, File.class);
                res = ZipUtil.zip(new File(url), false, files);

            }else {
                jsonPath = PathUtil.tmpModuleDir(BizModule.MODEL_CAL)+ "/"+ DateUtil.format(new Date(),"yyyyMMddHHmmss")+".json";
                FileUtil.writeString(dataJsonStr,jsonPath,"utf-8");
                res = new File(jsonPath);
            }
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, res.getName());
            FileUtils.writeBytes(res.getAbsolutePath(), response.getOutputStream());
        }catch (Exception e) {
            log.error("下载失败",e);
        }finally {
            res.delete();
        }
    }

    @PostMapping("/vertical")
    @ApiOperation(value = "全球垂直-计算", notes = "全球垂直-计算", httpMethod = "POST")
    public AjaxResult verticalCal(@RequestBody DynamicReviseVerticalVo vo){

        String area = CommonUtil.getArea(vo.getLongitudeRange(), vo.getLatitudeRange());
        String height = "["+ vo.getHeightRange() +"]";
        String ratio = "[" + vo.getInterval() + "," + vo.getHeightInterval() + "]";
        String codePath = PathUtil.codeModuleDir(BizModule.MODEL_CAL) + PathUtil.moduleDirs().getModelCal().get("dynamicVertical");

        String command = "python "+codePath+" "+vo.getStartTime()+" "+vo.getEndTime()+" "+vo.getTimeStep()+" " +area +" "+height +" "+ratio+" "+vo.getTypes()+" "+vo.getFrequence();
        String results = ExecUtil.execCmdWithResult(command);
            if (results == null || !results.contains("###")){
            return AjaxResult.error(results);
        }
        String[] splitArr = results.split("###");
        String log = splitArr[0];
        String pngPathArrStr = splitArr[1];
        String jsonPathArrStr = splitArr[2];

        List<String> pngPathList = JSONUtil.parseArray(pngPathArrStr).toList(String.class);
        List<String> jsonPathList = JSONUtil.parseArray(jsonPathArrStr).toList(String.class);
        List<String> jsonStrList = jsonPathList.stream()
                .map(path -> {
                    return CommonUtil.readStrData(new File(path), null);
                })
                .collect(Collectors.toList());

        Map<String, Object> resultMap = MapUtil.builder(new HashMap<String, Object>())
                .put("log", log)
                .put("data", pngPathList)
                .put("tableData", jsonStrList)
                .build();

        List<String> resultDataList  =  new ArrayList<>();
        resultDataList.addAll(pngPathList);
        resultDataList.addAll(jsonPathList);

        resultMap.put("resultData", JSONUtil.toJsonStr(resultDataList));
        resultMap.put("module", ResultSaveModule.MODEL_CAL);
        resultMap.put("submodule", ResultSaveModule.MODEL_CAL_CORRECT);

        return AjaxResult.success(resultMap);
    }


}
